package http

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io"
	"log"
	"net"
	"net/url"
	"proxy/config"
	"strings"
	"time"
)

func SocketServe() {
	addr := config.GetListenAddr()
	tlsConfig := config.GetTlsConfig()
	conn, err := tls.Listen("tcp", addr, tlsConfig)
	if err != nil {
		log.Fatalln(err)
	}
	log.Printf("Https代理服务器启动：%s\n", addr)
	defer conn.Close()
	for {
		c, err := conn.Accept()
		if c == nil {
			fmt.Println("Client connection is nil")
			return
		}
		if err != nil {
			fmt.Println(err)
			return
		}
		go handleRequest(c)
	}
}

func handleRequest(client net.Conn) {
	defer close(client)
	var buf [4096]byte
	n, err := client.Read(buf[:])
	if err != nil {
		log.Println(err)
		return
	}
	var method, host, addr string
	fmt.Sscanf(string(buf[:bytes.IndexByte(buf[:], '\n')]), "%s%s", &method, &host)
	url, err := url.Parse(host)
	if err != nil {
		log.Println(err)
		return
	}
	if url.Opaque == "443" {
		addr = url.Scheme + ":443"
	} else {
		if strings.Contains(url.Host, ":") {
			addr = url.Host
		} else {
			addr = url.Host + ":80"
		}
	}
	log.Printf("Remote Addr: %s\n", addr)
	server, err := net.DialTimeout("tcp", addr, time.Minute)
	if err != nil {
		log.Println(err)
		return
	}
	//defer server.Close()

	if method == "CONNECT" {
		fmt.Fprint(client, "HTTP/1.0 200 Connection established\r\n")
	} else {
		server.Write(buf[:n])
	}
	go copyTo(server, client, "Server")
	copyTo(client, server, "Client")
	//go transfer(server, client)
	//go transfer(client, server)
}

func copyTo(dst, src net.Conn, direction string) {
	n, err := io.Copy(dst, src)
	if err != nil {
		log.Println(err)
	} else {
		log.Printf("Copy to %s %d bytes\n", direction, n)
	}
}

func close(c net.Conn) {
	if err := c.Close(); err != nil {
		log.Println(err)
	}
}
